package com.easyidea.its.domain.repository.base.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Projections;
import org.hibernate.type.NullableType;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.easyidea.its.domain.repository.base.BaseBeanRepository;

/**
 * 
 * @author hukn
 * 
 * @param <T>
 */
public class BaseBeanRepositoryImpl<T> extends HibernateDaoSupport implements BaseBeanRepository<T> {

	private Class<T> claz;

	@SuppressWarnings("unchecked")
	public BaseBeanRepositoryImpl() {
		this.claz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	protected Session getCurrentSession() {
		return getSession();
	}

	@SuppressWarnings("unchecked")
	public T mergeBean(Object entity) {
		return (T) getHibernateTemplate().merge(entity);
	}

	protected Criteria createCriteria() {
		return createPhysicsCriteria();
	}

	protected Criteria createPhysicsCriteria() {
		return getCurrentSession().createCriteria(this.claz);
	}

	@SuppressWarnings("unchecked")
	public T getBeanById(Serializable id) {
		return (T) createCriteria().add(Expression.eq("id", id)).uniqueResult();
	}

	public void saveOrUpdateBean(T bean) {
		getHibernateTemplate().saveOrUpdate(bean);
	}

	public void removeBean(T bean) {
		getHibernateTemplate().delete(bean);
	}

	public void removeBean(Serializable id) {
		T bean = this.getBeanById(id);
		if (bean != null) {
			this.removeBean(bean);
		}
	}

	protected int countBeans(Criteria criteria) {
		criteria.setProjection(Projections.rowCount());
		int count = (Integer) criteria.uniqueResult();
		criteria.setProjection(null);
		return count;
	}

	@SuppressWarnings("unchecked")
	protected Collection listBeans(Criteria criteria, int start, int size) {
		if (start > 0) {
			criteria.setFirstResult(start);
		}
		if (size > 0) {
			criteria.setMaxResults(size);
		}
		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	protected Collection<T> listBeansBySql(String sql, int start, int size) {
		Query query = this.getCurrentSession().createSQLQuery(sql);
		query.setFirstResult(start >= 0 ? start : 0);
		if (start > 0) {
			query.setFirstResult(start);
		}
		if (size > 0) {
			query.setMaxResults(size);
		}
		return query.list();
	}

	@SuppressWarnings("unchecked")
	protected Collection<T> listBeansBySql(String sql, int start, int size, Map<String, NullableType> scalar) {
		SQLQuery query = this.getCurrentSession().createSQLQuery(sql);
		query.setFirstResult(start >= 0 ? start : 0);
		if (start > 0) {
			query.setFirstResult(start);
		}
		if (size > 0) {
			query.setMaxResults(size);
		}
		for (String colnumName : scalar.keySet()) {
			query.addScalar(colnumName, scalar.get(colnumName));
		}
		return query.list();
	}

	@SuppressWarnings("unchecked")
	protected Collection<T> listBeansByHql(String hql, int start, int size, Object... paras) {
		Query query = this.getCurrentSession().createQuery(hql);
		query.setFirstResult(start >= 0 ? start : 0);
		if (start > 0) {
			query.setFirstResult(start);
		}
		if (size > 0) {
			query.setMaxResults(size);
		}
		int i = 0;
		for (Object para : paras) {
			query.setParameter(i++, para);
		}

		return query.list();

	}

	public T save(T bean) {
		getHibernateTemplate().saveOrUpdate(bean);
		return bean;
	}

	public boolean isRepeated(String propertyName, String propertyValue, String idpropertyName, Serializable idValue) {
		Criteria criteria = createCriteria().add(Expression.eq(propertyName, propertyValue)).add(Expression.ne(idpropertyName, idValue));
		if (criteria.list().size() > 0) {
			return true;
		}
		return false;
	}
	@SuppressWarnings("unchecked")
	public <E> E getBeanByHQL(Class<E> clazz, String hql) {
		Query query = this.getCurrentSession().createQuery(hql);
		return (E) query.uniqueResult();
	}
	@SuppressWarnings("unchecked")
	public <E> Collection<E> listBeansByHQL(Class<E> clazz, String hql, int firstResult, int maxResults) {
		Query query = this.getCurrentSession().createQuery(hql);
		if (firstResult > 0) {
			query.setFirstResult(firstResult);
		}
		if (maxResults > 0) {
			query.setMaxResults(maxResults);
		}
		return query.list();
	}	
}
